package com.jy.rhin.infra.uitl;

import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda;
import com.jy.rhin.domain.document.submission.entity.RhinCodeableVO;
import org.apache.ibatis.reflection.property.PropertyNamer;

import java.util.HashMap;
import java.util.Map;

/**
 * @author WeiQ
 * @date 2022/6/24 10:35
 * 获取JavaBean字段，将字段名称做为字符串返回 添加了缓存
 */
public class LambdaPropertyUtils {

    private static final Map<Class<?>, Map<String, String>> PROPERTY_NAE_MAP = new HashMap<>();

    /**
     * 根据javaBean的getter方法，获取字段名
     * 例: getter = {@link RhinCodeableVO#getText} , 返回 RhinCodeableVO.text
     * @param clazz
     * @param getter
     * @return
     * @param <T>
     */
    public static <T> String getClassFieldName(Class<T> clazz, SFunction<T, ?> getter) {
        SerializedLambda resolve = LambdaUtils.resolve(getter);
        String functionName = resolve.toString();
        if (PROPERTY_NAE_MAP.containsKey(clazz)) {
            Map<String, String> functionStringMap = PROPERTY_NAE_MAP.get(clazz);
            if (functionStringMap.containsKey(functionName)) {
                return functionStringMap.get(functionName);
            } else {
                String propertyName = get(clazz, resolve);
                functionStringMap.put(functionName, propertyName);
                return propertyName;
            }
        } else {
            Map<String, String> functionStringMap = new HashMap<>(16);
            String propertyName = get(clazz, resolve);
            functionStringMap.put(functionName, propertyName);
            PROPERTY_NAE_MAP.put(clazz, functionStringMap);
            return propertyName;
        }
    }

    public static <T> String getPropertyName(T entity, SFunction<T, ?> rhinCodingGetter) {
        Class clazz = entity.getClass();
        return getClassFieldName(clazz, rhinCodingGetter);
    }

    private static String get(Class<?> clazz, SerializedLambda resolve) {
        String fieldName = PropertyNamer.methodToProperty(resolve.getImplMethodName());
        return clazz.getSimpleName() + "." + fieldName;
    }

    private LambdaPropertyUtils() {
    }

}
